﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.IsolatedStorage;
using System.Xml.Serialization;
using System.Text.RegularExpressions;
using System.Net;
using System.Globalization;

using VirtualDigibox.Entities;

namespace VirtualDigibox.BusinessService
{
    public class ServiceFacade
    {
        IsolatedStorageFileStream isfs = null;
        IsolatedStorageFile isf = null;
        XmlSerializer serializer = new XmlSerializer(typeof(List<Channel>));

        List<Channel> Channels { get; set; }

        public ServiceFacade()
        {
            LoadLocalData();
        }

        private void LoadLocalData()
        {
            isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User |
        IsolatedStorageScope.Assembly | IsolatedStorageScope.Domain,
        typeof(System.Security.Policy.Url), typeof(System.Security.Policy.Url));

            isfs = new IsolatedStorageFileStream("channels.xml", FileMode.OpenOrCreate, FileAccess.ReadWrite, isf);
            if (isfs.Length > 0)
            {
                Channels = (List<Channel>)serializer.Deserialize(isfs);

            }

            if (Channels == null)
                Channels = new List<Channel>();
        }

        public void SaveChannels(List<Channel> channels, bool close)
        {
            isfs.SetLength(0);
            serializer.Serialize(isfs, channels);
            Channels = channels;
            if (close)
                isfs.Close();
        }

        public List<Channel> GetChannels()
        {
            if (Channels == null || Channels.Count == 0)
                Channels = RefreshChannels();
            return Channels;
        }

        public List<Channel> RefreshChannels()
        {
            string webPage = "";
            string URL = string.Format("http://www.kava.ee/?page=chn&cgid=1&cid=12&d={0}&m={1}&y={2}"
                    , DateTime.Now.Day.ToString()
                    , DateTime.Now.Month.ToString()
                    , DateTime.Now.Year.ToString()
                    );

            WebClient client = new WebClient();
            Stream data = client.OpenRead(URL);
            StreamReader reader = new StreamReader(data);
            string str = "";
            str = reader.ReadLine();
            while (str != null)
            {
                webPage += str;
                str = reader.ReadLine();
            }
            data.Close();
            string channelWebPage = webPage.Replace("\n", "");
            channelWebPage = channelWebPage.Replace("<td colspan=\"3\" class=\"page_channel\">", Environment.NewLine + "<td colspan=\"3\" class=\"page_channel\">");
            channelWebPage = channelWebPage.Replace("<td valign=\"top\" width=\"33%\" class=\"page_channel\">", Environment.NewLine + "<td valign=\"top\" width=\"33%\" class=\"page_channel\">");
            channelWebPage = channelWebPage.Replace("<td>", Environment.NewLine + "<td>");
            channelWebPage = channelWebPage.Replace("<div class=\"channellist\">", Environment.NewLine + "<div class=\"channellist\">");

            MatchCollection kanalid = Regex.Matches(channelWebPage, "<div\\sclass=\"channellist\"><a\\shref=\"\\?page=chn&amp;cgi" +
                                    "d=(?<GID>.*?)&amp;cid=(?<CID>.*?)&amp;.*\">(?<NAME>.*?)</a>");

            string kanalTemplate = "http://www.kava.ee/?page=chn&cgid={0}&cid={1}&d=[:d:]&m=[:m:]&y=[:y:]&clicktrack=hover,chn,{1}";
            
            foreach (Match kanal in kanalid)
            {
                string[] kanalRow = { kanal.Groups["GID"].Value
                                    ,kanal.Groups["CID"].Value
                                    };
                Channel channelToAdd = Channels.Where(f => f.Name == kanal.Groups["NAME"].Value).FirstOrDefault();

                if (channelToAdd == null)
                {
                    channelToAdd = new Channel();
                    Channels.Add(channelToAdd);
                }
                                    
                channelToAdd.Name = kanal.Groups["NAME"].Value;
                channelToAdd.FetchURL = string.Format(kanalTemplate, kanalRow);
            }
            return Channels;
        }

        public List<ScheduleItem> LoadScheduleByRange(Channel currentChannel, DateTime start, DateTime end)
        {
            List<ScheduleItem> items = currentChannel.ScheduleItems;
            if (items == null)
                items = new List<ScheduleItem>();

            ScheduleItem first = items.Where(f => f.Time.Date == start.Date).OrderBy(o => o.Time).FirstOrDefault();
            ScheduleItem last = items.Where(f => f.Time.Date == end.Date).OrderByDescending(o => o.Time).FirstOrDefault();

            List<DateTime> missingDays = new List<DateTime>();
            DateTime currentDate = start.Date;
            while (currentDate.Date < end.Date)
            {
                ScheduleItem currentDay = currentChannel.ScheduleItems.Where(f => f.Time.Date == start.Date).FirstOrDefault();
                if (currentDay == null)
                    missingDays.Add(currentDate);
                currentDate = currentDate.AddDays(1).Date;
            }

            List<ScheduleItem> dayItems = new List<ScheduleItem>();
            
            foreach (DateTime day in missingDays)
            {
                if (dayItems.Where(f => f.Time.Date == day.Date).Count() == 0)
                    dayItems = LoadScheduleByStart(currentChannel, day);

                if (dayItems != null && dayItems.Count > 0)
                    items.AddRange(dayItems.Where(f => f.Time.Date >= day && f.Time.Date < day.Date.AddDays(1)) );
            }
            return items.OrderBy(o => o.Time).ToList();
        }

        private List<ScheduleItem> LoadScheduleByStart(Channel currentChannel, DateTime start)
        {
            string webPage = "";

            string fetchUrl = currentChannel.FetchURL.Replace("[:d:]", "{0}");
            fetchUrl = fetchUrl.Replace("[:m:]", "{1}");
            fetchUrl = fetchUrl.Replace("[:y:]", "{2}");

            string URL = string.Format(fetchUrl, start.Day.ToString(), start.Month.ToString(), start.Year.ToString());
            WebClient client = new WebClient();
            Stream data = client.OpenRead(URL);
            StreamReader reader = new StreamReader(data);
            string str = "";
            str = reader.ReadLine();
            while (str != null)
            {
                webPage += str;
                str = reader.ReadLine();
            }
            data.Close();
            string ahaa = webPage.Replace("\n", "");
            ahaa = ahaa.Replace("<td colspan=\"3\" class=\"page_channel\">", Environment.NewLine + "<td colspan=\"3\" class=\"page_channel\">");
            ahaa = ahaa.Replace("<td valign=\"top\" width=\"33%\" class=\"page_channel\">", Environment.NewLine + "<td valign=\"top\" width=\"33%\" class=\"page_channel\">");
            ahaa = ahaa.Replace("<td>", Environment.NewLine + "<td>");
            ahaa = ahaa.Replace("<div class=\"channellist\">", Environment.NewLine + "<div class=\"channellist\">");

            MatchCollection kava = Regex.Matches(ahaa, "(?:<div\\sclass=\"channeltitle\">(?<ChannelTitle>.*?)</div>|" +
      "<div\\sclass=\"sub\">\\w\\s(?<Date>.*)</div>|<div\\sclass=\"t" +
      "ime\">(?<Time>.*?)</div><div\\sclass=\"title\"><input\\stype" +
      "=\"hidden\"\\sid=\".*\"\\svalue=\".*?;;+(?<Desc>.*?);;+.*;;+" +
      ".*\"><a\\sid=\".*?\"\\shref=\".*?\"\\sclass=\"normal\".*?>(?" +
      "<Heading>.*?)</a>)");

            DateTime currentDate = new DateTime();
            List<ScheduleItem> scItems = new List<ScheduleItem>();

            foreach (Match row in kava)
            {
                if (row.Groups["ChannelTitle"].Success)
                {
                    continue;
                }
                if (row.Groups["Date"].Success)
                {
                    currentDate = DateTime.ParseExact(row.Groups["Date"].Value, "dd.MM.yyyy", CultureInfo.InvariantCulture);
                }

                if (row.Groups["Time"].Success && row.Groups["Heading"].Success)
                {
                    ScheduleItem sc = new ScheduleItem();
                    sc.Time = currentDate.Add(TimeSpan.Parse(row.Groups["Time"].Value));

                    if (row.Groups["Heading"].Success)
                    {
                        sc.BroadcastName = row.Groups["Heading"].Value;
                    }

                    if (row.Groups["Desc"].Success)
                    {
                        sc.Description = row.Groups["Desc"].Value;
                    }
                    scItems.Add(sc);
                }
            } // foreach
            return scItems;
        }
    }
}
